package vnreal.ZNEW.Algorithms;

import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.TransformerFactoryConfigurationError;

import org.apache.log4j.Logger;

import vnreal.ZNEW.XmlTest;
import vnreal.ZNEW.GraphTest.CostHelper;
import vnreal.ZNEW.GraphTest.Link;
import vnreal.ZNEW.GraphTest.Node;
import vnreal.ZNEW.GraphTest.SubstrateLink;
import vnreal.ZNEW.GraphTest.WorkOnPaths;
import vnreal.algorithms.AbstractSequentialAlgorithm;
import vnreal.gui.dialog.MyProgressBarDialog;
import vnreal.map.Map;
import vnreal.network.virtual.VirtualLink;

public abstract class Algorithms extends AbstractSequentialAlgorithm<VirtualLink>{
	public Logger log = Logger.getLogger(Algorithms.class);
	List<Link> bestLinks = new ArrayList<Link>();
	Link bestLink = new Link();
	static int numberOfVirtualLinks;
	int numberOfMappedVirtualLinks;

	
	protected Algorithms() {
		preInit();
		init();
		postInit();
	}

	private void preInit() {
		new MyProgressBarDialog(this);
		XmlTest.deserialize();
		Map.doPreCheck();

		if (Map.isSubstrateNodesExists) {
			WorkOnPaths.getNodes();
		}
		if (Map.isSubstrateLinksExists) {
			WorkOnPaths.getLinks();
		}
		if (Map.isVirtualNetworksExists) {
			WorkOnPaths.getVirtual();
		}
		checkNumberOfVirtualLinks();
	}

	protected abstract void init();

	private void postInit() {
		WorkOnPaths.addDemand();
		checkNodeEnergyConsumption();
		checkEnergyConsumption();
		checkNumberOfMappedVirtualLinks();
		checkDelays();
		try {
			XmlTest.serialize();

		} catch (TransformerFactoryConfigurationError e1) {
			e1.printStackTrace();
		}
		System.out.println("-----------------------After Algorithm:-----------------------\n\n\n\n");
		System.out.println(this);
	}
	private void checkNumberOfVirtualLinks() {
		numberOfVirtualLinks = WorkOnPaths.virtualEdges.size();
	}

	private void checkNodeEnergyConsumption() {
		WorkOnPaths.energyConsumption = .0;
		for (Node node : WorkOnPaths.substrateNodes) {
			if (node.isOn) {
				node.energyConsumption = .0;
				node.energyConsumption += CostHelper.CostOfNodeOn * Double.valueOf(node.energy);
				node.energyConsumption += CostHelper.turnOnLineCard * node.lineCards;
				node.energyConsumption += CostHelper.turnOnPort * node.ports;
			}
		}
	}

	private void checkEnergyConsumption() {
		WorkOnPaths.energyConsumption = .0;
		for (Node node : WorkOnPaths.substrateNodes) {
			if (node.isOn) {
				WorkOnPaths.energyConsumption += node.energyConsumption;
			}
		}
	}

	private void checkNumberOfMappedVirtualLinks() {
		numberOfMappedVirtualLinks = WorkOnPaths.virtualEdges.size();
	}

	private void checkDelays() {
		for (Link link : WorkOnPaths.virtualEdges) {
			for (SubstrateLink sLink : link.paths.get(0).subLink) {
				if (sLink.typeOfLink.equals("Copper")) {
					link.delay += Double.parseDouble(sLink.length) * 5.65;
				} else if (sLink.typeOfLink.equals("Fiber")) {
					link.delay += Double.parseDouble(sLink.length) * 4.89;
				}
			}
		}
	}

	private List<String> getEnabledNodes() {
		List<String> enabledNodes = new ArrayList<String>();
		for (Node node : WorkOnPaths.substrateNodes) {
			if (node.isOn) {
				enabledNodes.add(node.globalNodeId);
			}
		}
		return enabledNodes;
	}

	@Override
	public String toString() {
		String s = "";
		s += WorkOnPaths.toString2();
		s += "Enable Nodes: \n";
		s += getEnabledNodes() + "\n";
		s += "VL : " + numberOfVirtualLinks + ", Mapped VL: " + numberOfMappedVirtualLinks;
		return s;
	}

	public String saveToFile() {
		return WorkOnPaths.toString2();
	}
}